<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <title>工程测算</title>
    <link rel="stylesheet" href="./main.css">
    <style>
        .main {
            font-size: .12rem;
            width: 6rem;
            position: relative;
        }

        .button {
            background-color: burlywood;
            border-radius: .4rem;
            text-align: center;
            vertical-align: middle;
            color: white;
        }
        .lab {
            min-width: .8rem;
            text-align: justify;
        }
    </style>
</head>

<body>
    <div class="normal_column_start_center">
        <div class="main" v-cloak>
            <!-- 目标数量 -->
            <div class="m_t_10 normal_column_start_center full_width">
                <div class="full_width normal_row">
                    <span class="flex_shrink lab">目标期望值：</span>
                    <input class="font_size_12 flex_1" v-model="result" type="number" placeholder="请输入期望目标值">
                </div>
                <!-- <div class="m_t_10 full_width button"> 清除 </div> -->
            </div>
            <!-- 输入配置项 -->
            <div class="normal_column_start_center m_t_10 full_width">
                <div class="full_width normal_row">
                    <span class="flex_shrink lab">配置项名称：</span>
                    <input class="m_t_10 font_size_12 flex_1" type="text" v-model="name" placeholder="请输入配置项名称">
                </div>
                <div class="full_width normal_row">
                    <span class="flex_shrink lab">数量：</span>
                    <input class="m_t_10 font_size_12 flex_1" type="number" v-model="num" placeholder="请输入配置项数量">
                </div>
                <div class="full_width normal_row">
                    <span class="flex_shrink lab">固定占比：</span>
                    <input class="m_t_10 font_size_12 flex_1" type="number" v-model="persent" placeholder="请输入配置项固定占比（单位%）">
                </div>
                <div class="m_t_10 full_width button" @click="addParam"> 添加 </div>
            </div>
            <!-- 展示计算 -->
            <div class="m_t_10 normal_row" v-if="result">
                <span>{{ result }}</span>
                <span class="pa_15"> = </span>
                <div class="normal_row" style="flex-wrap: wrap;">
                    <div v-for="(item,index) in list" :key="index" class="normal_row m_l_5">
                        <span v-if="item.persent && !isNaN(item.persent)">（{{ item.persent }} %</span>
                        <span v-else>（ ?? %</span>
                        <span class="m_l_5"> * </span>
                        <span class="m_l_5"> {{ item.num }} </span>
                        <span class="m_l_5"> [{{ item.name }}]）</span>
                        <span class="m_l_5" v-if="index != (list.length - 1)"> + </span>
                    </div>
                </div>
            </div>
            <div v-if="result && list.length" class="m_t_10 full_width button" @click="begin"> 开始计算 </div>
            <!-- 展示结果 -->
            <div class="normal_row m_t_10 sep_bottom" style="position:sticky;top: 0;background-color: white;height: .35rem;">
                <div class="result_cell">总和</div>
                <div v-for="(item, index) in list" class="m_l_15 normal_row result_cell normal_row_center">
                    <span>{{ item.name }}</span>
                    <span>{{ '(' + item.num + ')'}}</span>
                </div>
            </div>
            <div class="normal_row m_t_10 sep_bottom" v-for="(item, index) in allResultArr" style="height: .35rem;">
                <div class="result_cell">{{ item.totalNum }}</div>
                <div v-for="(cellItem, index) in item.tempAssembly" class="m_l_15 normal_row result_cell normal_row_center">
                    <span>{{ cellItem.persent + ' %' }}</span>
                </div>
            </div>
            <!--  -->
        </div>
    </div>

</body>
<script type="text/javascript" src="./vue.min.js"></script>
<script type="text/javascript" src="./rem.js"></script>
<script type="text/javascript" src="./math.min.js"></script>
<script type="text/javascript" src="./floatOperation.js"></script>

<script>
    var vm = {}
    function InitVue () {
        vm = new Vue({
            el: '.main',
            data: {
                list:[],
                result:null,
                name:null,
                num:null,
                persent:null,
                floatOperation: new FloatOperation(),
                restNum:0,
                //可配置比例的选项
                allUnitaries:[],
                //总的计算结果
                allResultArr:[],
                //入栈出栈
                assembly:[],
                havePersentItems:[],
                id:0,
                exsitNum:0,
                maxDifferenceValue:0
            },
            mounted(){
                // this.result = 1000
                // this.list = [
                //     { name:'水泥', num:221 },
                //     { name:'木材', num:3443 },
                //     { name:'沙发', num:2121 },
                //     { name:'床', num:2324 },
                //     // { name:'椅子', num:2000 },
                //     // { name:'粉笔', num:2000 }
                // ]
            },
            methods:{
                addParam(){
                    if(this.result == null || this.result == ''){
                        alert('请输入目标期望值')
                        return
                    }
                    if(this.name == null || this.name == ''){
                        alert('请输入配置项名称')
                        return
                    }
                    if(this.num == null || this.num == ''){
                        alert('请输入配置项数量')
                        return
                    }
                    if(this.persent && this.persent % 5 != 0){
                        alert('固定占比须为5的整数倍')
                        return
                    }
                    if(this.persent && (this.persent < 0 || this.persent > 100)){
                        alert('固定占比须在0～100之间')
                        return
                    }
                    let name = this.name + ''
                    let persent = this.persent + ''
                    let num = this.num + ''
                    this.id = this.id + 1
                    let id = this.id
                    this.list.push({ name, persent, num, id })
                    this.name = ''
                    this.persent = ''
                    this.num = ''
                },
                begin(){
                    this.maxDifferenceValue = this.result * 0.05
                    this.havePersentItems = this.list.filter((item)=>{
                        return item.persent && item.persent != '' && !isNaN(item.persent)
                    })
                    let havePersentItems = this.list.filter((item)=>{
                        return item.persent && item.persent != '' && !isNaN(item.persent)
                    })
                    havePersentItems = havePersentItems.length ? havePersentItems.map((item)=>{
                        return this.floatOperation.floatMultiplication(item.num,this.floatOperation.floatDivision(item.persent,100))
                    }) : havePersentItems
                    let exsitNum = havePersentItems.length ? havePersentItems.reduce((prev, cur, index, arr)=>{
                        return this.floatOperation.floatAdd(prev,cur)
                    }) : 0
                    this.exsitNum = exsitNum
                    // 剩余需要填充的
                    let restNum = this.floatOperation.floatSubtracting(this.result,exsitNum)
                    // console.log('restNum:' + restNum)
                    // 可支配的
                    let noHavePersentItems = this.list.filter((item)=>{
                        return item.persent == '' || item.persent == null || isNaN(item.persent)
                    })
                    let totleNum = noHavePersentItems.length ? noHavePersentItems.map((item)=>{
                        return item.num
                    }).reduce((prev, cur, index, arr)=>{
                        return this.floatOperation.floatAdd(prev,cur)
                    }) : 0
                    if(exsitNum - this.result >= 0){
                        alert('固定比例配置项总和已超过或等于数量期望值，请调整部分配置项数量')
                        return
                    }
                    if(totleNum - restNum < 0){
                        alert('可配置项数量之和仍不满足期望值，请调整部分配置项数量')
                        return
                    }
                    // 计算可配置项比例
                    this.compute(restNum,noHavePersentItems)
                },
                // 计算可配置项比例
                compute(restNum,noHavePersentItems){
                    this.allResultArr = []
                    //单项集合
                    let allUnitaries = noHavePersentItems.map((item)=>{
                        let arr = []
                        for(let i = 0;i <= 100;i+=5){
                            arr.push({ name:item.name, num:this.floatOperation.floatMultiplication(item.num,i / 100),persent: i,id:item.id })
                        }
                        return arr
                    })

                    this.allUnitaries = allUnitaries
                    this.restNum = restNum
                    this.recursionComputeOption(0,restNum)
                    // console.log('this.allResultArr:' + this.allResultArr.length)
                    if(this.allResultArr.length == 0){
                        alert('未找到合适的组合')
                    }
                },
                recursionComputeOption(index,restNum){
                    if(index < this.allUnitaries.length){
                        let singleUnitaries = this.allUnitaries[index]
                        singleUnitaries.forEach((item,forEarchIndex)=>{
                            while(this.assembly.length > index){
                                this.assembly.pop()
                            }
                            this.assembly.push(item)
                            if(index == this.allUnitaries.length - 1){
                                let tempAssembly = [].concat(this.assembly)
                                let totalNum = tempAssembly.map((item)=>{
                                    return item.num
                                }).reduce((prev, cur, index, arr)=>{
                                    return this.floatOperation.floatAdd(prev,cur)
                                })
                                totalNum = this.floatOperation.floatAdd(totalNum,this.exsitNum)
                                let differenceValue = this.result - totalNum
                                if(differenceValue >= 0 && differenceValue < this.maxDifferenceValue){
                                    tempAssembly = tempAssembly.concat(this.havePersentItems ? this.havePersentItems : [])
                                    tempAssembly = tempAssembly.sort((a,b)=>{
                                        return a.id - b.id
                                    })
                                    // console.log('tempAssembly:' + JSON.stringify(tempAssembly))
                                    this.allResultArr.push({ totalNum, tempAssembly})
                                }
                            }
                            this.recursionComputeOption(index + 1,restNum)
                        })
                    }
                }
                //下一个方法
            }
        })
    }
    InitVue()
</script>

</html>